package com.smart.manager.system.handler;


import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.smart.common.entities.domain.TaskResult;
import com.smart.manager.system.entities.enums.TaskRunMode;
import com.smart.manager.system.entities.enums.TaskRunResult;
import com.smart.manager.system.entities.models.SystemScheduleApp;
import com.smart.manager.system.entities.models.SystemScheduleRecord;
import com.smart.manager.system.entities.models.SystemScheduleTask;
import com.smart.manager.system.entities.views.TaskView;
import com.smart.manager.system.repository.ScheduleTaskRepository;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.ReflectionUtils;

import java.lang.reflect.Method;
import java.time.LocalDateTime;

/**
 * 通过反射的方式 调用真定需要执行的方法
 * 并将当前对象封装成Runnable 子类
 *
 * @author Administrator
 */
@Slf4j
@AllArgsConstructor
@Data
public class TaskRunHandler implements Runnable {
    private final SystemScheduleTask task;


    @Override
    public void run() {
        SystemScheduleTask task = this.task;
        //建立一个简单的对象用来关联查询
        TaskView taskView = new TaskView(task.getId());
        SystemScheduleApp app = task.getApp();
        SystemScheduleRecord log = new SystemScheduleRecord().setTask(taskView).setRunMode(TaskRunMode.AUTOMATIC).setRunTime(LocalDateTime.now());
        boolean useParams = StrUtil.isNotBlank(task.getParams());
        try {
            Object target = SpringUtil.getBean(task.getApp().getBeanName());
            Class<?> aClass = target.getClass();
            Method method = useParams ? aClass.getDeclaredMethod(app.getMethodName(), String.class) : aClass.getDeclaredMethod(app.getMethodName());
            ReflectionUtils.makeAccessible(method);
            Object invoke = useParams ? method.invoke(target, task.getParams()) : method.invoke(target);
            TaskResult result = (TaskResult) invoke;
            TaskRunResult runResult = result.getStatus() ? TaskRunResult.SUCCESS : TaskRunResult.FAIL;

            log.setRunResult(runResult).setMessage(result.getMessage());
        } catch (Exception e) {
            String message = String.format("定时任务执行异常 :BEAN: %s ,方法: %s,参数: %s ,消息：%s", app.getBeanName(), app.getMethodName(), task.getParams(), e.getMessage());
            log.setRunResult(TaskRunResult.FAIL).setMessage(message);
        } finally {
            SpringUtil.getBean(ScheduleTaskRepository.class).updateLastRunTime(task.getId());
            log.save();
        }
    }

}